package com.young4j.xinsuiwutuobang.util;

import java.lang.reflect.Field;
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;

import com.young4j.xinsuiwutuobang.annotation.Inject;

/**
 * 不通过new的方式实例化，而是通过框架本身来实例化，像这类实例化过程，称为IOC（Inversion of Control，控制反转）。
 * 控制不是由开发者来决定的，而是反转个框架了，一般的也将控制反转称为DI（Dependency Injection，依赖注入），可理解为
 * 将某个类需要依赖的成员注入到这个类中。
 * 实现依赖注入，最简单的方法是，先通过BeanHelper获取所有BeanMap Map<Class<?>,Object> -类与对象的映射关系，
 * 然后遍历整个映射关系，分别取得Bean类与Bean实例，从而通过反射获取类中所有的成员变量。
 * 继续遍历这些成员变量，在循环中判断当前成员变量是否带有Inject注解，若带有该注解，则从BeanMap中根据Bean类取出Bean实例。最后通过ReflectionUtils#setFiled方法
 * 来修改当前成员变量的值
 * @author 杨飞
 *
 */
public final class IocHelper {
	/**
	 * IOC容器的初始化工作。
	 * 类被加载的时候调用静态块，需要找一个统一的地方来加载IocHelper
	 */
	static{
		//获取所有Bean类与Bean实例之间的映射关系-Ban Map
		Map<Class<?>,Object> beanMap = BeanHelper.getBean();
		if(CollectionUtils.isNotEmpty(beanMap)){
			for(Map.Entry<Class<?>, Object> beanEntity : beanMap.entrySet()){
				Class<?> beanClass = beanEntity.getKey();
				Object beanInstance = beanEntity.getValue();
				Field[] beanFields = beanClass.getDeclaredFields();
				if(ArrayUtils.isNotEmpty(beanFields)){
					for(Field beanField : beanFields){
						if(beanField.isAnnotationPresent(Inject.class)){
							Class<?> beanFieldClass = beanField.getType();
							if(beanFieldClass != null){
								ReflectionUtils.setField(beanFieldClass, beanField, beanInstance);
							}
						}
					}
				}
			}
		}
	}
	
}
